[id].vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <template>
  2. <div class="max-w-screen-xl content my-0 mx-auto text-size-base overflow-hidden">
  3. <div v-if="detail">
  4. <div class="breadcrumb my-[30px] pb-[20px] bb-1px_#EBEBEB" role="navigation">
  5. <n-breadcrumb separator=">" v-if="breadcrumb">
  6. <!-- {{ breadcrumb }} -->
  7. <template v-for="(bread, index) in breadcrumb" :key="index">
  8. <n-breadcrumb-item :clickable="false"> {{ bread.title }}</n-breadcrumb-item>
  9. </template>
  10. </n-breadcrumb>
  11. </div>
  12. <div v-if="currentCate">
  13. <n-h2 class="mb-10"> {{ currentCate.title }}</n-h2>
  14. </div>
  15. <div class="w-full flex flex-row flex-nowrap">
  16. <div class="flex-basis-[240px] flex-grow-0 flex-shrink-0 br-1px_#EBEBEB">
  17. <n-tree
  18. class="left-tree"
  19. v-if="mainCategories.children"
  20. block-line
  21. :data="mainCategories.children"
  22. :default-expanded-keys="defaultExpandedKeys"
  23. :node-props="nodeProps"
  24. key-field="id"
  25. label-field="title"
  26. children-field="children"
  27. selectable
  28. />
  29. <!-- <n-collapse class="br-1px_#EBEBEB py-[10px]">-->
  30. <!-- <template v-for="(cate, index) in mainCategories.children" :key="index">-->
  31. <!-- <n-collapse-item :title="cate.title" :name="cate.title">-->
  32. <!-- <n-collapse v-if="cate.children">-->
  33. <!-- <template v-for="(cateChild, cIndex) in cate.children" :key="cIndex">-->
  34. <!-- <n-collapse-item :title="cateChild.title" :name="cateChild.title">-->
  35. <!-- <div class="px-6">{{ cateChild.title }}</div>-->
  36. <!-- </n-collapse-item>-->
  37. <!-- </template>-->
  38. <!-- </n-collapse>-->
  39. <!-- <div class="px-6" v-else>{{ cate.title }}</div>-->
  40. <!-- </n-collapse-item>-->
  41. <!-- </template>-->
  42. <!-- </n-collapse>-->
  43. </div>
  44. <div class="flex-1 w-[calc(100%-80px)] px-[40px] mb-[120px] overflow-hidden">
  45. <div class="bb-1px_#EBEBEB color-[#999999]">
  46. <n-h1 class="font-700"> {{ detail.title }}</n-h1>
  47. <span class="flex flex-row gap-col-6 pb-[15px]">
  48. <p>发布于{{ dayjs(detail.createTime).format('YYYY-MM-DD') }}</p>
  49. <p>阅读 ( {{ detail.readCount }} )</p>
  50. </span>
  51. </div>
  52. <div class="w-full content-html" v-html="detail.content"></div>
  53. </div>
  54. <div class="flex-basis-[240px] flex-grow-0 flex-shrink-0">
  55. <div class="min-h-[200px] bg-[#F5F9FF] b-r-[8px] p-[20px]">
  56. <n-h4 class="font-600 ext-size-base">主要内容</n-h4>
  57. <n-anchor :show-rail="false">
  58. <n-anchor-link
  59. class="text-size-base color-[#999999]"
  60. v-for="(item, index) in mainContents"
  61. :key="index"
  62. :title="item.text"
  63. :href="`#my-section-${index + 1}`"
  64. >
  65. </n-anchor-link>
  66. </n-anchor>
  67. </div>
  68. </div>
  69. </div>
  70. </div>
  71. </div>
  72. </template>
  73. <route>
  74. {
  75. name: "showdoc",
  76. meta: {
  77. layout: "base"
  78. }
  79. }
  80. </route>
  81. <script setup lang="ts">
  82. import {
  83. type ArticleDetailType,
  84. type ArticleDetailMenuType,
  85. type CategoryItem,
  86. getArticleDetail,
  87. getArticleCount,
  88. getCategoryTree,
  89. getArticlesByCateId,
  90. } from '@/api'
  91. import { htmlToTree, createAnchorNames, dayjs, findNodeById, findBreadcrumbPath, type TreeNode } from '@/utils'
  92. import { NH1, NH2, NH4, NBreadcrumb, NBreadcrumbItem, NTree, NAnchor, NAnchorLink } from 'naive-ui'
  93. import type { TreeOption } from 'naive-ui'
  94. const route = useRoute()
  95. const router = useRouter()
  96. const params = route.params as {
  97. id?: number
  98. }
  99. const breadcrumb = ref<CategoryItem[]>([])
  100. console.log('route', route)
  101. const detail = ref<ArticleDetailType | undefined>()
  102. const mainContents = ref<ArticleDetailMenuType[]>([])
  103. const currentCate = ref<CategoryItem | undefined>()
  104. const mainCategories = ref<CategoryItem[]>([])
  105. const defaultExpandedKeys = ref<number[]>([])
  106. const nodeProps = ({ option }: { option: TreeOption }) => {
  107. return {
  108. async onClick() {
  109. // window.$message.info(`[Click] ${option.title},[ID] ${option.id} `)
  110. const res = await getArticlesByCateId(+(option.id as string))
  111. // console.log(res.data)
  112. if (res.data && res.data.length > 0) {
  113. const articleId = res.data[0].id
  114. console.log('articleId', articleId)
  115. // location.reload()
  116. router.replace(`/showdoc/${articleId}`)
  117. setTimeout(() => {
  118. location.reload()
  119. }, 500)
  120. } else {
  121. window.$message.info(`当前类别没有相关联的文章!`)
  122. }
  123. },
  124. }
  125. }
  126. onMounted(async () => {
  127. setTimeout(() => {
  128. const html = document.querySelector('.content-html')
  129. if (html) {
  130. createAnchorNames(html)
  131. }
  132. }, 1000)
  133. if (params.id) {
  134. await getArticleCount(+params.id)
  135. }
  136. })
  137. watchEffect(() => {
  138. if (params.id) {
  139. getArticleDetail(+params.id).then(async (data) => {
  140. if (data.data) {
  141. detail.value = data.data
  142. document.title = detail.value.title
  143. mainContents.value = htmlToTree(detail.value.content)
  144. if (detail.value.categoryId) {
  145. const res = await getCategoryTree(detail.value.categoryId)
  146. if (res.data) {
  147. mainCategories.value = res.data as CategoryItem[]
  148. if (mainCategories.value) {
  149. debugger
  150. currentCate.value = findNodeById(
  151. mainCategories.value as unknown as TreeNode[] ||[],
  152. String(detail.value.categoryId),
  153. ) as unknown as CategoryItem
  154. defaultExpandedKeys.value = [currentCate.value.parentId]
  155. breadcrumb.value = findBreadcrumbPath(mainCategories.value as unknown as TreeNode[] ||[], String(detail.value.categoryId))
  156. console.log('breadcrumb', breadcrumb.value)
  157. }
  158. }
  159. }
  160. }
  161. })
  162. }
  163. })
  164. </script>
  165. <style lang="scss" scoped>
  166. :deep(.content-html img) {
  167. width: 100% !important;
  168. height: auto;
  169. }
  170. :deep(.left-tree) {
  171. //--n-node-content-height: 40px !important;
  172. //--n-node-color-hover: rgba(6,97,201,0.06) !important;
  173. //border-right: 1px solid #e5e7eb;
  174. .n-tree-node-wrapper {
  175. width: 240px;
  176. font-size: 16px;
  177. }
  178. }
  179. </style>